#include "sdk.h"
#include "projectlayoutloader.h"
#include <tinyxml.h>
#include "tinywxuni.h"

ProjectLayoutLoader::ProjectLayoutLoader( M_Code_Project* project )
  : m_pProject( project ),
    m_TopProjectFile( nullptr ) {
}

ProjectLayoutLoader::~ProjectLayoutLoader() {
}

bool ProjectLayoutLoader::Open( const wxString& filename ) {
  TiXmlDocument doc;
  if( !TinyXML::LoadDocument( filename, &doc ) ) {
    return false;
  }
  ProjectManager* pMan = Manager::Get()->GetProjectManager();
  LogManager* pMsg = Manager::Get()->GetLogManager();
  if( !pMan || !pMsg ) {
    return false;
  }
  TiXmlElement* root;
  TiXmlElement* elem;
  wxString fname;
  ProjectFile* pf;
  root = doc.FirstChildElement( "m_Code_layout_file" );
  if( !root ) {
    pMsg->Log( _T( "无效的布局文件..." ) );
    return false;
  }
  // @todo (m#1#2019年07月19日): 改进打开项目自动定位到上次编译项目
  elem = root->FirstChildElement( "ActiveTarget" );
  if( elem ) {
    if( elem->Attribute( "name" ) ) {
      m_pProject->SetActiveBuildTarget( cbC2U( elem->Attribute( "name" ) ) );
    }
  }
  elem = root->FirstChildElement( "File" );
  if( !elem ) {
    return false;
  }
  while( elem ) {
    fname = cbC2U( elem->Attribute( "name" ) );
    if( fname.IsEmpty() ) {
      pf = nullptr;
    } else
    { pf = m_pProject->GetFileByFilename( fname ); }
    if( pf ) {
      pf->editorOpen = false;
      pf->editorSplit = M_Code_Editor::stNoSplit;
      pf->editorSplitActive = 1;
      pf->editorZoom = 0;
      pf->editorPos = 0;
      pf->editorTopLine = 0;
      pf->editorZoom_2 = 0;
      pf->editorPos_2 = 0;
      pf->editorTopLine_2 = 0;
      int getInt = 0;
      if( elem->QueryIntAttribute( "open", &getInt ) == TIXML_SUCCESS ) {
        pf->editorOpen = getInt != 0;
      }
      if( elem->QueryIntAttribute( "top", &getInt ) == TIXML_SUCCESS ) {
        if( getInt ) {
          m_TopProjectFile = pf;
        }
      }
      if( elem->QueryIntAttribute( "tabpos", &getInt ) == TIXML_SUCCESS ) {
        pf->editorTabPos = getInt;
      }
      if( elem->QueryIntAttribute( "split", &getInt ) == TIXML_SUCCESS ) {
        pf->editorSplit = getInt;
      }
      if( elem->QueryIntAttribute( "active", &getInt ) == TIXML_SUCCESS ) {
        pf->editorSplitActive = getInt;
      }
      if( elem->QueryIntAttribute( "splitpos", &getInt ) == TIXML_SUCCESS ) {
        pf->editorSplitPos = getInt;
      }
      if( elem->QueryIntAttribute( "zoom_1", &getInt ) == TIXML_SUCCESS ) {
        pf->editorZoom = getInt;
      }
      if( elem->QueryIntAttribute( "zoom_2", &getInt ) == TIXML_SUCCESS ) {
        pf->editorZoom_2 = getInt;
      }
      TiXmlElement* cursor = elem->FirstChildElement( "Cursor" );
      if( cursor ) {
        cursor = cursor->FirstChildElement();
        if( cursor ) {
          if( cursor->QueryIntAttribute( "position", &getInt ) == TIXML_SUCCESS ) {
            pf->editorPos = getInt;
          }
          if( cursor->QueryIntAttribute( "topLine", &getInt ) == TIXML_SUCCESS ) {
            pf->editorTopLine = getInt;
          }
          if( pf->editorSplit != M_Code_Editor::stNoSplit ) {
            cursor = cursor->NextSiblingElement();
            if( cursor ) {
              if( cursor->QueryIntAttribute( "position", &getInt ) == TIXML_SUCCESS )
              { pf->editorPos_2 = getInt; }
              if( cursor->QueryIntAttribute( "topLine", &getInt ) == TIXML_SUCCESS )
              { pf->editorTopLine_2 = getInt; }
            }
          }
        }
      }
      TiXmlElement* folding = elem->FirstChildElement( "Folding" );
      if( folding ) {
        folding = folding->FirstChildElement();
        while( folding ) {
          if( folding->QueryIntAttribute( "line", &getInt ) == TIXML_SUCCESS ) {
            pf->editorFoldLinesArray.Add( getInt );
          }
          folding = folding->NextSiblingElement();
        }
      }
    }
    elem = elem->NextSiblingElement();
  }
  if( ( Manager::Get()->GetConfigManager( _T( "app" ) )->ReadBool( _T( "/environment/enable_editor_layout" ), false ) ) ) {
    elem = root->FirstChildElement( "EditorTabsLayout" );
    if( elem ) {
      m_NotebookLayout = cbC2U( elem->Attribute( "layout" ) );
    }
  }
  return true;
}

bool ProjectLayoutLoader::Save( const wxString& filename ) {
  const char* ROOT_TAG = "m_Code_layout_file";
  TiXmlDocument doc;
  doc.SetCondenseWhiteSpace( false );
  doc.InsertEndChild( TiXmlDeclaration( "UTF-8", "yes" ) );
  TiXmlElement* rootnode = static_cast<TiXmlElement*>( doc.InsertEndChild( TiXmlElement( ROOT_TAG ) ) );
  if( !rootnode ) {
    return false;
  }
  TiXmlElement* tgtidx = static_cast<TiXmlElement*>( rootnode->InsertEndChild( TiXmlElement( "ActiveTarget" ) ) );
  tgtidx->SetAttribute( "name", cbU2C( m_pProject->GetActiveBuildTarget() ) );
  ProjectFile* active = nullptr;
  M_Code_Editor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
  if( ed ) {
    active = ed->GetProjectFile();
  }
  for( FilesList::iterator it = m_pProject->GetFilesList().begin(); it != m_pProject->GetFilesList().end(); ++it ) {
    ProjectFile* f = *it;
    if( f->editorOpen || f->editorPos || f->editorPos_2 || f->editorTopLine || f->editorTopLine_2 || f->editorTabPos ) {
      TiXmlElement* node = static_cast<TiXmlElement*>( rootnode->InsertEndChild( TiXmlElement( "File" ) ) );
      node->SetAttribute( "name", cbU2C( f->relativeFilename ) );
      node->SetAttribute( "open", f->editorOpen );
      node->SetAttribute( "top", ( f == active ) );
      node->SetAttribute( "tabpos", f->editorTabPos );
      node->SetAttribute( "split", f->editorSplit );
      node->SetAttribute( "active", f->editorSplitActive );
      node->SetAttribute( "splitpos", f->editorSplitPos );
      node->SetAttribute( "zoom_1", f->editorZoom );
      node->SetAttribute( "zoom_2", f->editorZoom_2 );
      TiXmlElement* cursor = static_cast<TiXmlElement*>( node->InsertEndChild( TiXmlElement( "Cursor" ) ) );
      TiXmlElement* cursor_1 = static_cast<TiXmlElement*>( cursor->InsertEndChild( TiXmlElement( "Cursor1" ) ) );
      cursor_1->SetAttribute( "position", f->editorPos );
      cursor_1->SetAttribute( "topLine", f->editorTopLine );
      if( f->editorSplit != M_Code_Editor::stNoSplit ) {
        TiXmlElement* cursor_2 = static_cast<TiXmlElement*>( cursor->InsertEndChild( TiXmlElement( "Cursor2" ) ) );
        cursor_2->SetAttribute( "position", f->editorPos_2 );
        cursor_2->SetAttribute( "topLine", f->editorTopLine_2 );
      }
      if( f->editorFoldLinesArray.GetCount() > 0 ) {
        TiXmlElement* folding = static_cast<TiXmlElement*>( node->InsertEndChild( TiXmlElement( "Folding" ) ) );
        for( unsigned int i = 0; i < f->editorFoldLinesArray.GetCount(); i++ ) {
          TiXmlElement* line = static_cast<TiXmlElement*>( folding->InsertEndChild( TiXmlElement( "Collapse" ) ) );
          line->SetAttribute( "line", f->editorFoldLinesArray[i] );
        }
      }
    }
  }
  const wxArrayString& en = m_pProject->ExpandedNodes();
  for( unsigned int i = 0; i < en.GetCount(); ++i ) {
    if( !en[i].IsEmpty() ) {
      TiXmlElement* node = static_cast<TiXmlElement*>( rootnode->InsertEndChild( TiXmlElement( "Expand" ) ) );
      node->SetAttribute( "folder", cbU2C( en[i] ) );
    }
  }
  if( Manager::Get()->GetConfigManager( _T( "app" ) )->ReadBool( _T( "/environment/enable_editor_layout" ), false ) ) {
    TiXmlElement *el =
      static_cast<TiXmlElement*>(
        rootnode->InsertEndChild( TiXmlElement( "EditorTabsLayout" ) ) );
    el->SetAttribute( "layout", cbU2C( Manager::Get()->GetEditorManager()->GetNotebook()->SavePerspective( m_pProject->GetTitle() ) ) );
  }
  return cbSaveTinyXMLDocument( &doc, filename );
}
